package de.pernpas.stadtfuehrer.phaselistener;

import java.util.logging.Logger;

import javax.faces.application.NavigationHandler;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletRequest;

import de.pernpas.stadtfuehrer.common.Sites;
import de.pernpas.stadtfuehrer.entity.Role;
import de.pernpas.stadtfuehrer.entity.User;

public class Authenticator implements PhaseListener {

	private static final long serialVersionUID = 1L;
	private static final Logger log = Logger.getLogger(Authenticator.class.getName());

	@Override
	public void afterPhase(PhaseEvent evt) {
		log.info("...after RESTORE_VIEW");
		FacesContext ctx = evt.getFacesContext();
		// get Action
		String action = getActionMethod(ctx);
		
		// If no action send, in case direct requesting a resource, get the requested URI
		if(action == null){
			HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
			action = request.getRequestURI();
		}
			
		if(action.contains("admin")){
			if(!hasUserAdminRole(ctx)){
				redirectToLogin(ctx);
			}
		}
	}

	private void redirectToLogin(FacesContext ctx) {
		NavigationHandler nh = ctx.getApplication().getNavigationHandler();
        nh.handleNavigation(ctx, null, Sites.LOGIN);
	}

	private boolean hasUserAdminRole(FacesContext ctx) {
		boolean hasAdminRole = false;
		User user = (User) ctx.getExternalContext().getSessionMap().get(User.class.getName());
		if (user != null) {
			for (Role role : user.getRoles()) {
				if (role == Role.ADMIN) {
					hasAdminRole = true;
					break;
				}
			}
		}
		return hasAdminRole;
	}

	private String getActionMethod(FacesContext ctx) {
		String methodExpression  = null;
	    if (ctx.isPostback()) {
	        UIViewRoot viewRoot = ctx.getViewRoot();
	        for (String clientId : ctx.getExternalContext().getRequestParameterMap().keySet()) {
	            UIComponent component = viewRoot.findComponent(clientId);
	            if (component instanceof UICommand) {
	                methodExpression = ((UICommand) component).getActionExpression().getExpressionString(); // It'll contain #{bean.action}.
	                log.info("methodExpression: " + methodExpression);
	                break; // There shouldn't be more than one anyway.
	            }
	        }
	    }
		return methodExpression;
	}

	@Override
	public void beforePhase(PhaseEvent arg0) {
	}

	@Override
	public PhaseId getPhaseId() {
		return PhaseId.RESTORE_VIEW;
	}

}
